package com.ruoyi.jt808.util;

import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * JT808协议转义工具类
 * 
 * <pre>
 * 0x7d01 <====> 0x7d
 * 0x7d02 <====> 0x7e
 * </pre>
 * 
 * @author hylexus
 *
 */
public class JT808ProtocolUtils {
	private final Logger log = LoggerFactory.getLogger(getClass());
	private BitOperator bitOperator;
	private BCD8421Operater bcd8421Operater;

	public JT808ProtocolUtils() {
		this.bitOperator = new BitOperator();
		this.bcd8421Operater = new BCD8421Operater();
	}

	/**
	 * 接收消息时转义<br>
	 * 
	 * <pre>
	 * 0x7d01 <====> 0x7d
	 * 0x7d02 <====> 0x7e
	 * </pre>
	 * 
	 * @param bs
	 *            要转义的字节数组
	 * @param start
	 *            起始索引
	 * @param end
	 *            结束索引
	 * @return 转义后的字节数组
	 * @throws Exception
	 */
	public byte[] doEscape4Receive(byte[] bs, int start, int end) throws Exception {
		if (start < 0 || end > bs.length)
			throw new ArrayIndexOutOfBoundsException("doEscape4Receive error : index out of bounds(start=" + start
					+ ",end=" + end + ",bytes length=" + bs.length + ")");
		ByteArrayOutputStream baos = null;
		try {
			baos = new ByteArrayOutputStream();
			for (int i = 0; i < start; i++) {
				baos.write(bs[i]);
			}
			for (int i = start; i < end - 1; i++) {
				if (bs[i] == 0x7d && bs[i + 1] == 0x01) {
					baos.write(0x7d);
					i++;
				} else if (bs[i] == 0x7d && bs[i + 1] == 0x02) {
					baos.write(0x7e);
					i++;
				} else {
					baos.write(bs[i]);
				}
			}
			for (int i = end - 1; i < bs.length; i++) {
				baos.write(bs[i]);
			}
			return baos.toByteArray();
		} catch (Exception e) {
			throw e;
		} finally {
			if (baos != null) {
				baos.close();
				baos = null;
			}
		}
	}

	/**
	 * 
	 * 发送消息时转义<br>
	 * 
	 * <pre>
	 *  0x7e <====> 0x7d02
	 * </pre>
	 * 
	 * @param bs
	 *            要转义的字节数组
	 * @param start
	 *            起始索引
	 * @param end
	 *            结束索引
	 * @return 转义后的字节数组
	 * @throws Exception
	 */
	public byte[] doEscape4Send(byte[] bs, int start, int end) throws Exception {
		if (start < 0 || end > bs.length)
			throw new ArrayIndexOutOfBoundsException("doEscape4Send error : index out of bounds(start=" + start
					+ ",end=" + end + ",bytes length=" + bs.length + ")");
		ByteArrayOutputStream baos = null;
		try {
			baos = new ByteArrayOutputStream();
			for (int i = 0; i < start; i++) {
				baos.write(bs[i]);
			}
			for (int i = start; i < end; i++) {
				if (bs[i] == 0x7e) {
					baos.write(0x7d);
					baos.write(0x02);
				} else {
					baos.write(bs[i]);
				}
			}
			for (int i = end; i < bs.length; i++) {
				baos.write(bs[i]);
			}
			return baos.toByteArray();
		} catch (Exception e) {
			throw e;
		} finally {
			if (baos != null) {
				baos.close();
				baos = null;
			}
		}
	}

	public int generateMsgBodyProps(int msgLen, int enctyptionType, boolean isSubPackage, int reversed_14_15) {
		// [ 0-9 ] 0000,0011,1111,1111(3FF)(消息体长度)
		// [10-12] 0001,1100,0000,0000(1C00)(加密类型)
		// [ 13_ ] 0010,0000,0000,0000(2000)(是否有子包)
		// [14-15] 1100,0000,0000,0000(C000)(保留位)
		if (msgLen >= 1024)
			log.warn("The max value of msgLen is 1023, but {} .", msgLen);
		int subPkg = isSubPackage ? 1 : 0;
		int ret = (msgLen & 0x3FF) | ((enctyptionType << 10) & 0x1C00) | ((subPkg << 13) & 0x2000)
				| ((reversed_14_15 << 14) & 0xC000);
		return ret & 0xffff;
	}

	public byte[] generateMsgHeader(String phone, int msgType, byte[] body, int msgBodyProps, int flowId)
			throws Exception {
		ByteArrayOutputStream baos = null;
		try {
			baos = new ByteArrayOutputStream();
			// 1. 消息ID word(16)
			baos.write(bitOperator.integerTo2Bytes(msgType));
			// 2. 消息体属性 word(16)
			baos.write(bitOperator.integerTo2Bytes(msgBodyProps));
			// 3. 终端手机号 bcd[6]
			baos.write(bcd8421Operater.string2Bcd(phone));
			// 4. 消息流水号 word(16),按发送顺序从 0 开始循环累加
			baos.write(bitOperator.integerTo2Bytes(flowId));
			// 消息包封装项 此处不予考虑
			return baos.toByteArray();
		} finally {
			if (baos != null) {
				baos.close();
			}
		}
	}

	public static byte[] covertByte(byte[] bs) {
		List<Byte> transByteList = new ArrayList<Byte>();
		for (int i = 0; i < bs.length; i++) {
			transByteList.add(bs[i]);
		}
		for (int i = transByteList.size() - 1; i >= 0; i--) {
			if (i == 0) {
				break;
			}
			if (transByteList.get(i - 1) == 0x7d && transByteList.get(i) == 0x02) {
				transByteList.remove(i);
				transByteList.set(i - 1, new Byte((byte)0x7e));

			} else if (transByteList.get(i - 1) == 0x7d && transByteList.get(i) == 0x01) {
				transByteList.remove(i);
				transByteList.set(i - 1, new Byte((byte)0x7d));
			}
		}

		byte[] transByte = new byte[transByteList.size()];
		for (int i = 0; i < transByteList.size(); i++) {
			transByte[i] = transByteList.get(i);
		}
		return transByte;
	}

	public int parseEBInDetail(byte[] ebData) {
		//String hexString = "7E020000EE0610006515543A79000000000000080001FADDCD0669529A0000000000002510071141150104000021FF30011F310100EBC4000C00B28986084810247076538700060089FFFFFFFF000600C5FFFFFFF70004002D0E58000300A828000B00D801CC0090830B3D3419001100D5383631303134303738373935353937007000B90545383A32323A38313A43393A46453A44302C2D37332C34343A44463A36353A39363A37373A30322C2D37332C32343A39373A34353A34333A36363A43382C2D37342C31363A44383A36343A31303A33433A41462C2D38392C31433A37333A45323A44313A35423A32392C2D39330007002A000000000AD37E";
		System.out.println("完整数据: " + bytesToHex(ebData));
        String hexData = bytesToHex(ebData);
        String hexString = hexData.replaceAll(" ", "");
        System.out.println(hexString);
		hexString= hexString.substring(hexString.indexOf("0104"));
		int position = hexString.indexOf("00A8");
		if (position != -1) {
			System.out.println("找到 '00A8' 在位置: " + position);
			System.out.println("字节位置: " + (position / 2));

			System.out.println("电量字符: " + hexString.substring(position,position+2));

			int afterPosition = position + 4; // 00A8 占4个字符
			if (afterPosition + 2 <= hexString.length()) {
				String nextTwoChars = hexString.substring(afterPosition, afterPosition + 2);
				System.out.println("00A8 后面的两位字符是: " + nextTwoChars);

				// 显示完整上下文
				//showFullContext(hexString, position, 4);

				// 解析含义
				//parseMeaning(nextTwoChars);

				int decimalValue = Integer.parseInt(nextTwoChars, 16);
				System.out.println("电量百分比: " + decimalValue + "%");
				return decimalValue;
			} else {
				System.out.println("00A8 后面没有足够的字符");
			}

		} else {
			System.out.println("未找到 '00A8'");
		}
		return 0;
	}

	private static void showFullContext(String hexString, int position, int patternLength) {
		int start = Math.max(0, position - 10);
		int end = Math.min(hexString.length(), position + patternLength + 10);

		System.out.println("完整上下文:");
		String context = hexString.substring(start, end);
		System.out.println("..." + context + "...");

		// 标记位置
		System.out.print("   ");
		int markerPos = position - start;
		for (int i = 0; i < markerPos; i++) {
			System.out.print(" ");
		}
		System.out.print("00A8");

		// 标记后面的字符
		if (position + patternLength + 2 <= end) {
			for (int i = 0; i < 2; i++) {
				System.out.print(" ");
			}
			System.out.print("^^");
		}
		System.out.println();
	}

	private static String bytesToHex(byte[] bytes) {
		StringBuilder sb = new StringBuilder();
		for (byte b : bytes) {
			sb.append(String.format("%02X ", b));
		}
		return sb.toString().trim();
	}
}
